package com.lambkit.spring.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import com.lambkit.core.Lambkit;
import com.lambkit.core.service.ResourceService;
import com.lambkit.core.service.ScanFileProcess;
import com.lambkit.util.StringKit;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author yangyong(孤竹行)
 */
public class SpringResourceService implements ResourceService {

    private String webRootPath;
    private String rootClassPath;

    private String webSharePath;
    private String resourcePath;

    private String templatePath;

    @Override
    public String getRootClassPath(String resourcePathType) {
        if(rootClassPath==null) {
            String pathType = resourcePathType;
            if("classpath".equalsIgnoreCase(pathType) || "resources".equalsIgnoreCase(pathType)) {
                rootClassPath = ResourceUtils.CLASSPATH_URL_PREFIX;
            } else {
                rootClassPath = ClassUtil.getClassPath();
            }
//            if(Lambkit.isDevMode()) {
//                StaticLog.info("当前系统的rootClassPath目录：{}", rootClassPath);
//            }
        }
        return rootClassPath;
    }

    @Override
    public String getRootClassPath() {
        return getRootClassPath(Lambkit.context().getResourcePathType());
    }

    @Override
    public String getWebResourceClassPath(String resourcePath) {
        String prefix = resourcePath;
        if(prefix.startsWith("file:")) {
            prefix = prefix.substring(prefix.lastIndexOf("/"));
        }
        prefix = StringKit.removePrefix(prefix, "/");
        if (!prefix.endsWith("/")) {
            prefix = prefix + "/";
        }
        String path = ResourceUtils.CLASSPATH_URL_PREFIX + prefix;
        return path;
    }

    @Override
    public String getWebResourceWebRootPath(String resourcePath, String resourcePathType) {
        String webrootPath = null;
        String pathType = resourcePathType;
        if("classpath".equalsIgnoreCase(pathType) || "resources".equalsIgnoreCase(pathType)) {
            //共享资源放在jar同目录的webapp下
            String prefix = resourcePath;
            if(prefix.startsWith("file:")) {
                prefix = prefix.substring(prefix.lastIndexOf("/"));
            }
            prefix = StringKit.removePrefix(prefix, "/");
            if (!prefix.endsWith("/")) {
                prefix = prefix + "/";
            }
            webrootPath = getRootPath() + File.separator + prefix;
        } else {
            webrootPath = getWebRootPath(resourcePathType);
        }
        return webrootPath;
    }
    @Override
    public String getWebResourceFilePath(String resourcePath) {
        String path = resourcePath;
        if(path.startsWith("file:")) {
            //资源在外部指定的目录
            return path;
        }
        String webFilePath = null;
        String prefix = resourcePath;
        prefix = StringKit.removeSuffix(prefix, "/");
        if (!prefix.endsWith("/")) {
            prefix = prefix + "/";
        }
        webFilePath = getRootPath() + File.separator + prefix;
        return webFilePath;
    }

    @Override
    public List<String> getWebResourcePathList(String resourcePath, String resourcePathType) {
        List<String> pathList = CollUtil.newArrayList();

        String path = resourcePath;
        if(path.startsWith("file:")) {
            //资源在外部指定的目录
            pathList.add(path);
        }
        if(path.startsWith("file:")) {
            path = path.substring(5);
        }
        path = StringKit.removePrefix(path, "/");
        if (!path.endsWith("/")) {
            path = path + "/";
        }
        String resourceClassPath = ResourceUtils.CLASSPATH_URL_PREFIX + path;
        pathList.add(resourceClassPath);

        String resourceWebRootPath = getRootPath() + File.separator + path;
        pathList.add(resourceWebRootPath);

        URL resourceUrl = this.getClass().getResource("/");
        if(resourceUrl != null && !resourceUrl.getProtocol().equals("jar")) {
            String webrootPath = getWebRootPath(resourcePathType);
            pathList.add(webrootPath);
        }
        return pathList;
    }

    @Override
    public String getWebResourcePath(String resourcePath, String resourcePathType) {
        if(resourcePath==null) {
            String pathType = resourcePathType;
            if ("classpath".equalsIgnoreCase(pathType) || "resources".equalsIgnoreCase(pathType)) {
                String prefix = resourcePath;
                if(prefix.startsWith("file:")) {
                    prefix = prefix.substring(5);
                }
                prefix = StringKit.removePrefix(prefix, "/");
                if (!prefix.endsWith("/")) {
                    prefix = prefix + "/";
                }
                resourcePath = ResourceUtils.CLASSPATH_URL_PREFIX + prefix;
            } else {
                String prefix = resourcePath;
                if(prefix.startsWith("file:")) {
                    prefix = prefix.substring(prefix.lastIndexOf("/"));
                }
                if (!prefix.startsWith("/")) {
                    prefix = "/" + prefix;
                }
                prefix = StringKit.removeSuffix(prefix, "/");
                resourcePath = getWebRootPath(resourcePathType) + prefix;
            }
//            if(Lambkit.isDevMode()) {
//                StaticLog.info("当前系统的resourcePath目录：{}", resourcePath);
//            }
        }
       return resourcePath;
    }

    @Override
    public String getWebTemplatePath(String templatePath, String resourcePathType) {
        if(templatePath==null) {
            String pathType = resourcePathType;
            if ("classpath".equalsIgnoreCase(pathType) || "resources".equalsIgnoreCase(pathType)) {
                String prefix = templatePath;
                prefix = StringKit.removePrefix(prefix, "/");
                if (!prefix.endsWith("/")) {
                    prefix = prefix + "/";
                }
                templatePath = ResourceUtils.CLASSPATH_URL_PREFIX + prefix;
            } else {
                String prefix = templatePath;
                if (!prefix.startsWith("/")) {
                    prefix = "/" + prefix;
                }
                prefix = StringKit.removeSuffix(prefix, "/");
                templatePath = getWebRootPath(resourcePathType) + prefix;
            }
//            if(Lambkit.isDevMode()) {
//                StaticLog.info("当前系统的templatePath目录：{}", templatePath);
//            }
        }
        return templatePath;
    }

    @Override
    public String getWebSharePath(String resourcePath, String resourcePathType) {
        if(webSharePath==null) {
            String path = resourcePath;
            if(path.startsWith("file:")) {
                //资源在外部指定的目录
                webSharePath = path;
            } else {
                String pathType = resourcePathType;
                if("classpath".equalsIgnoreCase(pathType) || "resources".equalsIgnoreCase(pathType)) {
                    //共享资源放在jar同目录的webapp下
                    webSharePath = getRootPath() + File.separator + "webapp";
                } else {
                    webSharePath = getWebRootPath(resourcePathType);
                }
            }
//            if(Lambkit.isDevMode()) {
//                StaticLog.info("当前系统的webSharePath目录：{}", webSharePath);
//            }
        }
        return webSharePath;
    }

    @Override
    public String getWebRootPath(String resourcePathType) {
        if(webRootPath==null) {
            String pathType = resourcePathType;
            if("classpath".equalsIgnoreCase(pathType) || "resources".equalsIgnoreCase(pathType)) {
                webRootPath = ResourceUtils.CLASSPATH_URL_PREFIX;
            } else {
                webRootPath = detectWebRootPath();
            }
//            if(Lambkit.isDevMode()) {
//                StaticLog.info("当前系统的webRootPath目录：{}", webRootPath);
//            }
        }
        return webRootPath;
    }

    @Override
    public String getWebRootPath() {
        return getWebRootPath(Lambkit.context().getResourcePathType());
    }

    // 注意：命令行返回的是命令行所在路径的上层的上层路径
    private static String detectWebRootPath() {
        try {
            String path = ResourceUtils.CLASSPATH_URL_PREFIX;
            String ret = ResourceUtils.getFile(path).getParentFile().getParentFile().getCanonicalPath();
            // 支持 maven 项目在开发环境下探测 webRootPath
            if (path.endsWith("/target/classes/")) {
                return ret + "/src/main/resources";
            } else if (path.endsWith("\\target\\classes\\")) {
                return ret + "\\src\\main\\resources";
            } else {
                return ret;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String getRootPath() {
        String path = System.getProperty("user.dir");
//        if(Lambkit.isDevMode()) {
//            StaticLog.info("当前系统的user.dir运行目录：{}", path);
//        }
        //ClassLoader classLoader = getClass().getClassLoader();
        //String currentDir = classLoader.getResource("").getPath();
        //System.out.println("当前运行目录：" + currentDir);
        return path;
    }

    @Override
    public String getResourceFile(String fileName) {
        String filePath = null;
        String rootPath = getRootPath();
        //优先查找config下有没有properties
        String fileNamePath = rootPath + File.separator + "config" + File.separator + fileName;
        File file = new File(fileNamePath);
        if(file.exists()) {
            filePath = fileNamePath;
        } else {
            //优先查找root下有没有properties
            fileNamePath = rootPath + File.separator + fileName;
            if(file.exists()) {
                filePath = fileNamePath;
            } else {
                filePath = fileName;
            }
        }
        return filePath;
    }

    @Override
    public void scanFolder(String folderPath, String resourcePathType, ScanFileProcess fileProcess) {
        String pathType = resourcePathType;
        boolean isFile = true;
        if("classpath".equalsIgnoreCase(pathType)) {
            try {
                URL url = ResourceUtils.getURL(folderPath);
                if(url != null) {
                    isFile = false;
                    //System.out.println(getClass() + "url: " + url.toString());
                    //if(url != null && url.getProtocol().equals("classpath")) {
                    URLConnection urlConnection = url.openConnection();
                    if(urlConnection instanceof JarURLConnection) {
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        JarFile jarFile = jarURLConnection.getJarFile();
                        //System.out.println("Jar Entry: " + jarURLConnection.getJarEntry().getName());
                        for(Enumeration<JarEntry> enumeration = jarFile.entries(); enumeration.hasMoreElements(); ) {
                            JarEntry jarEntry = enumeration.nextElement();
                            fileProcess.process(jarFile, jarEntry);
                        }
                    } else {
                        isFile = true;
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        if(isFile) {
            File file = new File(folderPath);
            scanTemplateFloders(file, fileProcess);
        }
    }

    @Override
    public void scanFolder(String folderPath, ScanFileProcess fileProcess) {
        scanFolder(folderPath, Lambkit.context().getResourcePathType(), fileProcess);
    }

    private void scanTemplateFloders(File file, ScanFileProcess fileProcess) {
        boolean flag = fileProcess.process(file);
        if(flag) {
            return;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (null != files) {
                for (File f : files) {
                    scanTemplateFloders(f, fileProcess);
                }
            }
        }
    }
}
